﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_WIN_PLATFORM_H
#define _UXS_WIN_PLATFORM_H

#pragma once

#include "../Base/OSTypes.h"

#ifdef PLATFORM_WINDOWS_SHELL

#include "WKeyCodes.h"
#include "Window.h"

namespace UX_STL
{
namespace _platform_
{
	using namespace UXTypes;
	using namespace UXMath;
	using namespace winapi;

	#define NEWLINE			"\x0D\x0A"


	struct e_msg_buttons
	{
		enum	type :	uint32
		{
			OK						= MB_OK,
			OK_CANCEL				= MB_OKCANCEL,
			YES_NO					= MB_YESNO,
			YES_NO_CANCEL			= MB_YESNOCANCEL,
			ABORT_RETRY_IGNORE		= MB_ABORTRETRYIGNORE,
			RETRY_CANCEL			= MB_RETRYCANCEL,
			CANCEL_RETRY_CONTINUE	= MB_CANCELTRYCONTINUE,
		};
	};

	struct e_msg_button_ret
	{
		enum	type :	uint8
		{
			OK			= IDOK,
			CANCEL		= IDCANCEL,
			ABORT		= IDABORT,
			RETRY		= IDRETRY,
			IGNORE		= IDIGNORE,
			YES			= IDYES,
			NO			= IDNO,
			CLOSE		= IDCLOSE,
		};
	};
	


	//
	// WinAPI Platform (static functions only)
	//

	struct UX_EXPORT WinApiPlatform
	{
		static uvec2 ScreenResolution();
		static uvec2 ScreenPhysicalSize();

		static void  GetInstance (THandles &sHandles);
		static bool  GetModulePath (string &sPath, uni_c_string pModuleName);
		static bool  GetModulePath (string &sPath, void *pModule = null);
		static bool  GetSystemPath (string &sPath);

		static void* AllocPage (usize uPageSize);
		static bool  FreePage (void *pPage);
		
		static bool  GetDate (string &str, e_date::type eType);

		static bool  GetSystemInfo (TSystemInfo &sInfo);
		static void  GetSystemInfoString (const TSystemInfo &sInfo, string &sStr);
	
		static bool  SetTimer (const THandles &sHandles, uint32 &uTimer, uint uElapse);
		static bool  KillTimer (const THandles &sHandles, uint32 uTimer);
		
		static bool  ShowCursor (bool bShow);
		static bool  SetCursorPos (const ivec2 &vPos);
		
		static void  GetMemory (uint &uTotal, uint &uFree);
		static void  GetVirtualMemory (uint &uTotal, uint &uFree);

		static void  Yield ();
		static void  Delay (uint timeMSec);
		
		static bool  GetScreenModes (array<TScreenMode> &aModes);
		static bool  ChangeScreenResolution (const uvec2 &sScrRes, const uint8 uColors = 8, uint uFreq = 0);

		static e_msg_button_ret::type ErrorMsg (uni_c_string pCaption, uni_c_string pText, e_msg_buttons::type eButtons);
	};



	
//--------------------------- WinApiPlatform -----------------------------//
/*
=================================================
	
=================================================
*/
	inline void WinApiPlatform::GetInstance (THandles &sHandles)
	{
		sHandles.hInstance = GetModuleHandle( (LPCSTR) null );
	}
	
/*
=================================================
	
=================================================
*/
	inline void * WinApiPlatform::AllocPage (usize uPageSize)
	{
		return VirtualAlloc( null, uPageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
	}

/*
=================================================
	
=================================================
*/
	inline bool WinApiPlatform::FreePage (void *pPage)
	{
		return VirtualFree( pPage, 0, MEM_RELEASE ) == TRUE;
	}

/*
=================================================
	
=================================================
*/
	inline uvec2 WinApiPlatform::ScreenResolution ()
	{
		enum {
			SM_CXSCREEN	= 0,
			SM_CYSCREEN	= 1,
		};
		return uvec2( GetSystemMetrics( SM_CXSCREEN ),
					  GetSystemMetrics( SM_CYSCREEN ) );
	}

/*
=================================================
	
=================================================
*/
	inline uvec2 WinApiPlatform::ScreenPhysicalSize ()
	{
		enum {
			HORZSIZE	= 4,
			VERTSIZE	= 6,
		};
		uvec2	size;
		HDC		hDCScreen	= GetDC( null );
		
		size.x = GetDeviceCaps( hDCScreen, HORZSIZE );
		size.y = GetDeviceCaps( hDCScreen, VERTSIZE );
		
		ReleaseDC( null, hDCScreen );
		return size;
	}

/*
=================================================
	показать/скрыть курсор
=================================================
*/
	inline bool WinApiPlatform::ShowCursor (bool bShow)
	{
		int	i_show = bShow ? TRUE : FALSE;
		return winapi::ShowCursor( i_show ) == i_show;
	}
	
/*
=================================================
	установить курсор в заданую позицию
=================================================
*/
	inline bool WinApiPlatform::SetCursorPos (const ivec2 &vPos)
	{
		return winapi::SetCursorPos( vPos.x, vPos.y ) == TRUE;
	}

/*
=================================================
	возвращает полный размер оперативной памяти
	и размер свободной памяти (МБ)
=================================================
*/
	inline void WinApiPlatform::GetMemory (uint &uTotal, uint &uFree)
	{
		MEMORYSTATUSEX stat;
		stat.dwLength = sizeof(stat);
		GlobalMemoryStatusEx( &stat );
		uTotal = uint( stat.ullTotalPhys >> 20 );
		uFree  = uint( stat.ullAvailPhys >> 20 );
	}
	
/*
=================================================
	возвращает полный размер виртуальной памяти
	и размер свободной памяти (МБ)
=================================================
*/
	inline void WinApiPlatform::GetVirtualMemory (uint &uTotal, uint &uFree)
	{
		MEMORYSTATUSEX stat;
		stat.dwLength = sizeof(stat);
		GlobalMemoryStatusEx( &stat );
		uTotal = uint( stat.ullTotalVirtual >> 20 );
		uFree  = uint( stat.ullAvailVirtual >> 20 );
	}

/*
=================================================
	устанавливает таймер
=================================================
*/
	inline bool WinApiPlatform::SetTimer (const THandles &sHandles, uint32 &uTimer, uint uElapse)
	{
		return winapi::SetTimer( sHandles.hWnd, uTimer, uElapse, null ) != 0;
	}

/*
=================================================
	удалить таймер
=================================================
*/
	inline bool WinApiPlatform::KillTimer (const THandles &sHandles, uint32 uTimer)
	{
		return winapi::KillTimer( sHandles.hWnd, uTimer ) == TRUE;
	}
	
/*
=================================================
	приостановить процесс на минимальное время
=================================================
*/
	inline void WinApiPlatform::Yield ()
	{
		Sleep(1);
	}
	
/*
=================================================
	приостановить процесс на заданное время
=================================================
*/
	inline void WinApiPlatform::Delay (uint timeMSec)
	{
		Sleep(timeMSec);
	}
	
/*
=================================================
	вывести сообщение об ошибке
=================================================
*/
	inline e_msg_button_ret::type WinApiPlatform::ErrorMsg (uni_c_string pCaption, uni_c_string pText, e_msg_buttons::type eButtons)
	{
		return (e_msg_button_ret::type)
			MessageBox( null, pText.cstr(), pCaption.cstr(),
				eButtons | MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST );
	}

//-------------------------------------------------------------------

}	// UXTypesExt
}	// UX_STL

#endif	// PLATFORM_WINDOWS_SHELL

#endif	// _UXS_WIN_PLATFORM_H